home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gp_amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  22.5 KB  |  921 lines

  1. /* Copyright (C) 1989, 1992, 1993, 1994 Aladdin Enterprises.  All rights reserved.
  2.  
  3.   This file is part of Aladdin Ghostscript.
  4.  
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.  
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* gp_amiga.c */
  20. /* Amiga-specific routines for Ghostscript */
  21. #include <dos/dosextens.h>
  22. #include <graphics/gfxbase.h>
  23. #include <intuition/intuitionbase.h>
  24.  
  25. #include <proto/dos.h>
  26. #include <proto/exec.h>
  27. #include <proto/intuition.h>
  28.  
  29. #include <sys/types.h>
  30. #undef _POSIX_SOURCE
  31. #include <sys/dirent.h>
  32. typedef struct dirent dir_entry;
  33. #include "stat_.h"
  34. #include "string_.h"
  35. #include "time_.h"
  36. #include "gx.h"
  37. #include "gp.h"
  38. #include "gsexit.h"
  39. #include "gsstruct.h"
  40. #include "gsutil.h"
  41.  
  42. #include <signal.h>
  43. #include <stdlib.h>
  44. #include <unistd.h>
  45. #include <sys/param.h>    /* for MAXPATHLEN */
  46.  
  47. #if defined(mc68020)
  48.  #ifdef __HAVE_68881__
  49.   STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68020/FPU version\r\n";
  50.  #else
  51.   STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68020 version\r\n";
  52.  #endif    /* __HAVE_68881__ */
  53. #elif defined(mc68030)
  54.  #ifdef __HAVE_68881__
  55.   STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68030/FPU version\r\n";
  56.  #else
  57.   STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68030 version\r\n";
  58.  #endif    /* __HAVE_68881__ */
  59. #elif defined(mc68040)
  60.  #ifdef __HAVE_68881__
  61.   STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68040/FPU version\r\n";
  62.  #else
  63.   STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68040 version\r\n";
  64.  #endif    /* __HAVE_68881__ */
  65. #elif defined(mc68060)
  66.  #ifdef __HAVE_68881__
  67.   STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68060/FPU version\r\n";
  68.  #else
  69.   STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" GSDATE ") MC68060 version\r\n";
  70.  #endif    /* __HAVE_68881__ */
  71. #else
  72. STATIC STRPTR VersTag = "$VER: gs " GSVERSION " (" __DATE2__ ")\r\n";
  73. #endif    /* mc68020 */
  74.  
  75. /*struct IntuitionBase *IntuitionBase;
  76. struct GfxBase        *GfxBase;
  77. struct Library        *LayersBase,
  78.             *IFFParseBase,
  79.             *AslBase,
  80.             *UtilityBase;*/
  81. /*struct DosLibrary *DOSBase;
  82. struct MathIEEEBase *MathIeeeDoubBasBase;*/
  83.  
  84. /* Cleanup routine, as called by atexit() trap */
  85. void
  86. cleanup(void)
  87. {
  88.     extern void devcleanup(void);
  89.  
  90. //      devcleanup();
  91.  
  92. /*      if(IFFParseBase)
  93.     {
  94.         CloseLibrary(IFFParseBase);
  95.  
  96.         IFFParseBase = NULL;
  97.     }
  98.  
  99.     if(AslBase)
  100.     {
  101.         CloseLibrary(AslBase);
  102.  
  103.         AslBase = NULL;
  104.     }
  105.  
  106.     if(UtilityBase)
  107.     {
  108.         CloseLibrary(UtilityBase);
  109.  
  110.         UtilityBase = NULL;
  111.     }
  112.  
  113.     if(LayersBase)
  114.     {
  115.         CloseLibrary(LayersBase);
  116.  
  117.         LayersBase = NULL;
  118.     }
  119.  
  120.     if(GfxBase)
  121.     {
  122.         CloseLibrary((struct Library *)GfxBase);
  123.  
  124.         GfxBase = NULL;
  125.     }
  126.  
  127.     if(IntuitionBase)
  128.     {
  129.         CloseLibrary((struct Library *)IntuitionBase);
  130.  
  131.         IntuitionBase = NULL;
  132.     }*/
  133. }
  134.  
  135. /*void
  136. signal_handler(int signal)
  137. {
  138.     fprintf(stderr,"*** BREAK: Ghostscript\a\n");
  139.  
  140.     gs_exit(1);
  141. }*/
  142.  
  143. /* Do platform-dependent initialization. */
  144. void
  145. gp_init(void)
  146. {
  147.     atexit(cleanup);
  148.  
  149. //      signal(SIGINT,signal_handler);
  150.     
  151. /*      if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
  152.     {
  153.         eprintf("Ghostscript: cannot open intuition.library v37\n");
  154.  
  155.         exit(20);
  156.     }
  157.     
  158.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
  159.     {
  160.         eprintf("Ghostscript: cannot open graphics.library v37\n");
  161.  
  162.         exit(20);
  163.     }
  164.  
  165.     if(!(LayersBase = OpenLibrary("layers.library",37)))
  166.     {
  167.         eprintf("Ghostscript: cannot open layers.library v37\n");
  168.  
  169.         exit(20);
  170.     }
  171.  
  172.     if(!(UtilityBase = OpenLibrary("utility.library",37)))
  173.     {
  174.         eprintf("Ghostscript: cannot open utility.library v37\n");
  175.  
  176.         exit(20);
  177.     }*/
  178.  
  179. /*      if(!(IFFParseBase = OpenLibrary("iffparse.library",37)))
  180.     {
  181.         eprintf("Ghostscript: cannot open iffparse.library v37\n");
  182.  
  183.         exit(20);
  184.     }*/
  185.  
  186. //      AslBase = OpenLibrary("asl.library",38);
  187. }
  188.  
  189. /* Do platform-dependent cleanup. */
  190. void
  191. gp_exit(int exit_status, int code)
  192. {
  193.     cleanup();
  194. }
  195.  
  196. /* Exit the program. */
  197. void
  198. gp_do_exit(int exit_status)
  199. {    exit(exit_status);
  200. }
  201.  
  202. /* ------ Miscellaneous ------ */
  203.  
  204. /*
  205.  * Get the string corresponding to an OS error number.
  206.  * If no string is available, return NULL.  The caller may assume
  207.  * the string is allocated statically and permanently.
  208.  */
  209. const char *
  210. gp_strerror(int errnum)
  211. {    return (strerror(errnum));
  212. }
  213.  
  214. /* ------ Date and time ------ */
  215.  
  216. /* Read the current time (in seconds since Jan. 1, 1970) */
  217. /* and fraction (in nanoseconds). */
  218. void
  219. gp_get_realtime(long *pdt)
  220. {
  221. #if defined(IXEMUL)
  222.     struct timeval tp;
  223.  
  224.  #if gettimeofday_no_timezone            /* older versions of SVR4 */
  225.     {    if ( gettimeofday(&tp) == -1 )
  226.           {    lprintf("Ghostscript: gettimeofday failed!\n");
  227.             gs_exit(1);
  228.           }
  229.     }
  230.  #else                        /* All other systems */
  231.     {    struct timezone tzp;
  232.         if ( gettimeofday(&tp, &tzp) == -1 )
  233.           {    lprintf("Ghostscript: gettimeofday failed!\n");
  234.             gs_exit(1);
  235.           }
  236.     }
  237.  #endif
  238.     /* tp.tv_sec is #secs since Jan 1, 1970 */
  239.     pdt[0] = tp.tv_sec;
  240.  
  241.     /* Some Unix systems (e.g., Interactive 3.2 r3.0) return garbage */
  242.     /* in tp.tv_usec.  Try to filter out the worst of it here. */
  243.     pdt[1] = tp.tv_usec >= 0 && tp.tv_usec < 1000000 ? tp.tv_usec*1000 : 0;
  244.  
  245. #else
  246.     LONG secs, micros;
  247.  
  248.     CurrentTime(&secs, µs);
  249.  
  250.     pdt[0] = secs;
  251.     pdt[1] = micros*1000;
  252.  
  253. #endif
  254. #ifdef DEBUG_CLOCK
  255.     printf("tp.tv_sec = %d  tp.tv_usec = %d  pdt[0] = %ld  pdt[1] = %ld\n",
  256.         tp.tv_sec, tp.tv_usec, pdt[0], pdt[1]);
  257. #endif
  258. }
  259.  
  260. /* Read the current user CPU time (in seconds) */
  261. /* and fraction (in nanoseconds).  */
  262. void
  263. gp_get_usertime(long *pdt)
  264. {
  265. #if use_times_for_usertime
  266.     LONG secs, micros;
  267.  
  268.     CurrentTime(&secs, µs);
  269.  
  270.     pdt[0] = secs;
  271.     pdt[1] = micros*1000;
  272. #else
  273.     gp_get_realtime(pdt);    /* Use an approximation on other hosts.  */
  274. #endif
  275. }
  276.  
  277. /* ------ Screen management ------ */
  278.  
  279. /* Get the environment variable that specifies the display to use. */
  280. const char *
  281. gp_getenv_display(void)
  282. {    return getenv("DISPLAY");
  283. }
  284.  
  285. /* ------ Printer accessing ------ */
  286.  
  287. /* Open a connection to a printer.  A null file name means use the */
  288. /* standard printer connected to the machine, if any. */
  289. /* "|command" opens an output pipe. */
  290. /* Return NULL if the connection could not be opened. */
  291. FILE *
  292. gp_open_printer(char *fname, int binary_mode)
  293. {
  294. #ifndef IXEMUL
  295.     return
  296.       (strlen(fname) == 0 ?
  297.        gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "wb+") :
  298.        fname[0] == '|' ?
  299.        NULL :
  300.        fopen(fname, "wb+"));
  301. #else
  302.     return
  303.       (strlen(fname) == 0 ?
  304.        gp_open_scratch_file(gp_scratch_file_name_prefix, fname, "w") :
  305.        fname[0] == '|' ?
  306.        popen(fname + 1, "w") :
  307.        fopen(fname, "w"));
  308. #endif
  309. }
  310.  
  311. /* Close the connection to the printer. */
  312. void
  313. gp_close_printer(FILE *pfile, const char *fname)
  314. {
  315. #ifndef IXEMUL
  316.     fclose(pfile);
  317. #else
  318.     if ( fname[0] == '|' )
  319.         pclose(pfile);
  320.     else
  321.         fclose(pfile);
  322. #endif
  323. }
  324.  
  325. /* ------ File name syntax ------ */
  326.  
  327. /* Define the character used for separating file names in a list. */
  328. const char gp_file_name_list_separator = ',';
  329.  
  330. /* Define the string to be concatenated with the file mode */
  331. /* for opening files without end-of-line conversion. */
  332. const char gp_fmode_binary_suffix[] __attribute__ ((aligned (4))) = "";
  333. /* Define the file modes for binary reading or writing. */
  334. const char gp_fmode_rb[] __attribute__ ((aligned (4))) = "r";
  335. const char gp_fmode_wb[] __attribute__ ((aligned (4))) = "wb+";
  336.  
  337. /* Answer whether a file name contains a directory/device specification, */
  338. /* i.e. is absolute (not directory- or device-relative). */
  339. int
  340. gp_file_name_is_absolute(const char *fname, uint len)
  341. {
  342.     int i;
  343.  
  344.     for(i = 0 ; i < len ; i++)
  345.     {
  346.         if(fname[i] == ':')
  347.             return(1);
  348.     }
  349.  
  350.     return(0);
  351. }
  352.  
  353. /* Answer the string to be used for combining a directory/device prefix */
  354. /* with a base file name.  The file name is known to not be absolute. */
  355. const char *
  356. gp_file_name_concat_string(const char *prefix, uint plen, const char *fname, uint len)
  357. {
  358. #ifdef IXEMUL
  359.     if(plen > 0 && (prefix[plen - 1] == '/' || prefix[plen - 1] == ':'))
  360.         return("");
  361.     else
  362.         return("/");
  363. #else
  364.     if(plen > 0)
  365.         if(prefix[plen - 1] == '/' || prefix[plen - 1] == ':')
  366.             return("");
  367.         else
  368.             return("/");
  369.     else
  370.         return("");
  371. #endif
  372. }
  373.  
  374. /* ------ File naming and accessing ------ */
  375.  
  376. /* Define the default scratch file name prefix. */
  377. #ifdef IXEMUL
  378. const char gp_scratch_file_name_prefix[] = "/T/gs_";
  379. #else
  380. const char gp_scratch_file_name_prefix[] = "T:gs_";
  381. #endif
  382. /* Define the name of the null output file. */
  383. #ifdef IXEMUL
  384. const char gp_null_file_name[] = "/dev/null";
  385. #else
  386. const char gp_null_file_name[] = "NIL:";
  387. #endif
  388.  
  389. /* Define the name that designates the current directory. */
  390. #ifdef IXEMUL
  391. const char gp_current_directory_name[] = ".";
  392. #else
  393. const char gp_current_directory_name[] __attribute__ ((aligned (4))) = "";
  394. #endif
  395.  
  396. /* Create and open a scratch file with a given name prefix. */
  397. /* Write the actual file name at fname. */
  398. FILE *
  399. gp_open_scratch_file(const char *prefix, char *fname, const char *mode)
  400. {
  401. #ifndef IXEMUL
  402.     char temp2[100];
  403.     struct Task *thistask;
  404.     LONG secs, micros;
  405. #endif
  406.  
  407.     strcpy(fname,prefix);
  408.     /* Prevent trailing X's in path from being converted by mktemp. */
  409.     if ( *fname != 0 && fname[strlen(fname) - 1] == 'X' )
  410.         strcat(fname, "-");
  411. #ifdef IXEMUL
  412.     strcat(fname, "XXXXXX");
  413. #else
  414.     CurrentTime(&secs, µs);
  415.     sprintf(temp2,"%08lx_%08lx_%08lx",FindTask(NULL), secs, micros);
  416. /* this looks stupid but a reasonable chance exists that you end up with the
  417.    same time if scratch files are opened fast enough
  418. */
  419.     Delay(25);
  420.     strcat(fname, temp2);
  421. #endif
  422. #ifdef IXEMUL
  423.     mktemp(fname);
  424. #endif
  425.     return fopen(fname, mode);
  426. }
  427.  
  428. /* Open a file with the given name, as a stream of uninterpreted bytes. */
  429. FILE *
  430. gp_fopen(const char *fname, const char *mode)
  431. {    return fopen(fname, mode);
  432. }
  433.  
  434. /* ------ File enumeration ------ */
  435.  
  436. /* Thanks to Fritz Elfert (Fritz_Elfert@wue.maus.de) for */
  437. /* the original version of the following code, and Richard Mlynarik */
  438. /* (mly@adoc.xerox.com) for an improved version. */
  439.  
  440. typedef struct dirstack_s dirstack;
  441. struct dirstack_s {
  442.     dirstack *next;
  443.     struct DIR *entry;
  444. };
  445. gs_private_st_ptrs1(st_dirstack, dirstack, "dirstack",
  446.   dirstack_enum_ptrs, dirstack_reloc_ptrs, next);
  447.  
  448. struct file_enum_s
  449. {
  450.     struct DIR *dirp;         /* pointer to current open directory   */
  451.     char *pattern;        /* original pattern                    */
  452.     char *work;        /* current path                        */
  453.     int worklen;            /* strlen (work)               */
  454.     dirstack *dstack;    /* directory stack                     */
  455.     int patlen;
  456.     int pathead;            /* how much of pattern to consider
  457.                  *  when listing files in current directory */
  458.     bool first_time;
  459.     gs_memory_t *memory;
  460. };
  461. gs_private_st_ptrs3(st_file_enum, struct file_enum_s, "file_enum",
  462.   file_enum_enum_ptrs, file_enum_reloc_ptrs, pattern, work, dstack);
  463.  
  464. /* Private procedures */
  465.  
  466. /* Do a wild-card match. */
  467. #ifdef DEBUG
  468. private bool
  469. wmatch(const byte *str, uint len, const byte *pstr, uint plen,
  470.   const string_match_params *psmp)
  471. {    bool match = string_match(str, len, pstr, plen, psmp);
  472.     if ( gs_debug_c('e') )
  473.       { dputs("[e]string_match(\"");
  474.         fwrite(str, 1, len, dstderr);
  475.         dputs("\", \"");
  476.         fwrite(pstr, 1, plen, dstderr);
  477.         dprintf1("\") = %s\n", (match ? "TRUE" : "false"));
  478.       }
  479.     return match;
  480. }
  481. #define string_match wmatch
  482. #endif
  483.  
  484. /* Search a string backward for a character. */
  485. /* (This substitutes for strrchr, which some systems don't provide.) */
  486. private char *
  487. rchr(char *str, char ch, int len)
  488. {    register char *p = str + len;
  489.     while ( p > str )
  490.       if ( *--p == ch ) return p;
  491.     return 0;
  492. }
  493.  
  494. /* Pop a directory from the enumeration stack. */
  495. private bool
  496. popdir(file_enum *pfen)
  497. {    dirstack *d = pfen->dstack;
  498.     if ( d == 0 )
  499.       return false;
  500.     pfen->dirp = d->entry;
  501.     pfen->dstack = d->next;
  502.     gs_free_object(pfen->memory, d, "gp_enumerate_files(popdir)");
  503.     return true;
  504. }
  505.  
  506. /* Initialize an enumeration. */
  507. file_enum *
  508. gp_enumerate_files_init(const char *pat, uint patlen, gs_memory_t *mem)
  509. {    file_enum *pfen;
  510.     char *p;
  511.     char *work;
  512.  
  513.     /* Reject attempts to enumerate paths longer than the */
  514.     /* system-dependent limit. */
  515.     if ( patlen > MAXPATHLEN )
  516.         return 0;
  517.  
  518.     /* Reject attempts to enumerate with a pattern containing zeroes. */
  519.     {    const char *p1;
  520.         for (p1 = pat; p1 < pat + patlen; p1++)
  521.             if (*p1 == 0) return 0;
  522.     }
  523.         /* >>> Should crunch strings of repeated "/"'s in pat to a single "/"
  524.          * >>>  to match stupid unix filesystem "conventions" */
  525.  
  526.     pfen = gs_alloc_struct(mem, file_enum, &st_file_enum,
  527.                    "gp_enumerate_files");
  528.     if (pfen == 0)
  529.         return 0;
  530.  
  531.     /* pattern and work could be allocated as strings, */
  532.     /* but it's simpler for GC and freeing to allocate them as bytes. */
  533.  
  534.     pfen->pattern =
  535.       (char *)gs_alloc_bytes(mem, patlen + 1,
  536.                  "gp_enumerate_files(pattern)");
  537.     if (pfen->pattern == 0)
  538.         return 0;
  539.     memcpy(pfen->pattern, pat, patlen);
  540.     pfen->pattern[patlen] = 0;
  541.  
  542.     work = (char *)gs_alloc_bytes(mem, MAXPATHLEN+1,
  543.                       "gp_enumerate_files(work)");
  544.     if (work == 0)
  545.         return 0;
  546.     pfen->work = work;
  547.  
  548.     p = work;
  549.     memcpy(p, pat, patlen);
  550.     p += patlen;
  551.     *p = 0;
  552.  
  553.     /* Remove directory specifications beyond the first wild card. */
  554.     /* Some systems don't have strpbrk, so we code it open. */
  555.     p = pfen->work;
  556.     while ( !(*p == '*' || *p == '?' || *p == 0) ) p++;
  557.     while ( !(*p == '/' || *p == 0) ) p++;
  558.     if ( *p == '/' )
  559.       *p = 0;
  560.         /* Substring for first wildcard match */
  561.         pfen->pathead = p - work;
  562.  
  563.     /* Select the next higher directory-level. */
  564.         p = rchr(work, '/', p - work);
  565.         if (!p)
  566.       {    /* No directory specification */
  567.         work[0] = 0;
  568.         pfen->worklen = 0;
  569.       }
  570.         else
  571.       {    if (p == work)
  572.           {    /* Root directory -- don't turn "/" into "" */
  573.             p++;
  574.           }
  575.         *p = 0;
  576.         pfen->worklen = p - work;
  577.       }
  578.  
  579.     pfen->memory = mem;
  580.     pfen->dstack = 0;
  581.     pfen->first_time = true;
  582.     pfen->patlen = patlen;
  583.     return pfen;
  584. }
  585.  
  586. /* Enumerate the next file. */
  587. uint
  588. gp_enumerate_files_next(file_enum *pfen, char *ptr, uint maxlen)
  589. {    dir_entry *de;
  590.     char *work = pfen->work;
  591.     int worklen = pfen->worklen;
  592.     char *pattern = pfen->pattern;
  593.     int pathead = pfen->pathead;
  594.     int len;
  595.     struct stat stbuf;
  596.  
  597.     if ( pfen->first_time )
  598.       {    pfen->dirp = ((worklen == 0) ? opendir(".") : opendir(work));
  599.         if_debug1('e', "[e]file_enum:First-Open '%s'\n", work);
  600.         pfen->first_time = false;
  601.         if (pfen->dirp == 0)    /* first opendir failed */
  602.           {    gp_enumerate_files_close(pfen);
  603.             return ~(uint)0;
  604.           }
  605.       }
  606.  
  607.  top:    de = readdir(pfen->dirp);
  608.     if (de == 0)
  609.       {    /* No more entries in this directory */
  610.         char *p;
  611.  
  612.         if_debug0('e', "[e]file_enum:Closedir\n");
  613.         closedir(pfen->dirp);
  614.         /* Back working directory and matching pattern up one level */
  615.         p = rchr(work,'/', worklen);
  616.         if (p != 0)
  617.           {    if (p == work) p++;
  618.             *p = 0;
  619.             worklen = p - work;
  620.           }
  621.                 else
  622.                   worklen = 0;
  623.         p = rchr(pattern,'/', pathead);
  624.         if (p != 0)
  625.           pathead = p - pattern;
  626.         else
  627.           pathead = 0;
  628.  
  629.         if (popdir(pfen))
  630.           {    /* Back up the directory tree. */
  631.             if_debug1('e', "[e]file_enum:Dir popped '%s'\n", work);
  632.             goto top;
  633.           }
  634.         else
  635.           {    if_debug0('e', "[e]file_enum:Dirstack empty\n");
  636.             gp_enumerate_files_close(pfen);
  637.             return ~(uint)0;
  638.           }
  639.       }
  640.  
  641.     /* Skip . and .. */
  642.     len = strlen(de->d_name);
  643.     if (len <= 2 && (!strcmp(de->d_name,".") || !strcmp(de->d_name,"..") ))
  644.       goto top;
  645.     if (len + worklen + 1 > MAXPATHLEN)
  646.       /* Should be an error, I suppose */
  647.       goto top;
  648.     if (worklen == 0)
  649.       {    /* "Current" directory (evil un*x kludge) */
  650.         memcpy(work, de->d_name, len + 1);
  651.       }
  652.     else if (worklen == 1 && work[0] == '/')
  653.       {    /* Root directory */
  654.         memcpy(work + 1, de->d_name, len + 1);
  655.         len = len + 1;
  656.       }
  657.     else
  658.       {    work[worklen] = '/';
  659.         memcpy(work + worklen + 1, de->d_name, len + 1);
  660.         len = worklen + 1 + len;
  661.       }
  662.  
  663.     /* Test for a match at this directory level */
  664.     if (!string_match((byte *)work, len, (byte *)pattern, pathead, NULL))
  665.       goto top;
  666.  
  667.     /* Perhaps descend into subdirectories */
  668.     if (pathead < pfen->patlen)
  669.       {    struct DIR *dp;
  670.  
  671.         if (((stat(work,&stbuf) >= 0)
  672.              ? !stat_is_dir(stbuf)
  673.              /* Couldn't stat it.
  674.               * Well, perhaps it's a directory and
  675.               * we'll be able to list it anyway.
  676.               * If it isn't or we can't, no harm done. */
  677.              : 0))
  678.           goto top;
  679.  
  680.         if (pfen->patlen == pathead + 1)
  681.           {    /* Listing "foo/?/" -- return this entry */
  682.             /* if it's a directory. */
  683.             if (!stat_is_dir (stbuf))
  684.               {    /* Do directoryp test the hard way */
  685.                 dp = opendir(work);
  686.                 if (!dp) goto top;
  687.                 closedir(dp);
  688.               }
  689.             work[len++] = '/';
  690.             goto winner;
  691.           }
  692.  
  693.         /* >>> Should optimise the case in which the next level */
  694.         /* >>> of directory has no wildcards. */
  695.         dp = opendir(work);
  696. #ifdef DEBUG
  697.         {    char save_end = pattern[pathead];
  698.             pattern[pathead] = 0;
  699.             if_debug2('e', "[e]file_enum:fname='%s', p='%s'\n",
  700.                   work, pattern);
  701.             pattern[pathead] = save_end;
  702.         }
  703. #endif /* DEBUG */
  704.         if (!dp)
  705.           /* Can't list this one */
  706.           goto top;
  707.         else
  708.           {    /* Advance to the next directory-delimiter */
  709.             /* in pattern */
  710.             char *p;
  711.                         dirstack *d;
  712.             for (p = pattern + pathead + 1; ; p++)
  713.               {    if (*p == 0)
  714.                   {    /* No more subdirectories to match */
  715.                     pathead = pfen->patlen;
  716.                     break;
  717.                   }
  718.                 else if (*p == '/')
  719.                   {    pathead = p - pattern;
  720.                     break;
  721.                   }
  722.               }
  723.  
  724.                         /* Push a directory onto the enumeration stack. */
  725.                         d = gs_alloc_struct(pfen->memory, dirstack,
  726.                                             &st_dirstack,
  727.                                             "gp_enumerate_files(pushdir)");
  728.                         if ( d != 0 )
  729.                         {
  730.                           d->next  = pfen->dstack;
  731.                           d->entry = pfen->dirp;
  732.                           pfen->dstack = d;
  733.                         }
  734.                         else
  735.                           DO_NOTHING; /* >>> e_VMerror!!! */
  736.  
  737.             if_debug1('e', "[e]file_enum:Dir pushed '%s'\n",
  738.                   work);
  739.             worklen = len;
  740.             pfen->dirp = dp;
  741.             goto top;
  742.           }
  743.       }
  744.  
  745.  winner:
  746.     /* We have a winner! */
  747.     pfen->worklen = worklen;
  748.     pfen->pathead = pathead;
  749.     memcpy(ptr, work, len);
  750.     return len;
  751. }
  752.  
  753. /* Clean up the file enumeration. */
  754. void
  755. gp_enumerate_files_close(file_enum *pfen)
  756. {    gs_memory_t *mem = pfen->memory;
  757.  
  758.     if_debug0('e', "[e]file_enum:Cleanup\n");
  759.     while (popdir(pfen))    /* clear directory stack */
  760.           DO_NOTHING;
  761.     gs_free_object(mem, (byte *)pfen->work,
  762.                "gp_enumerate_close(work)");
  763.     gs_free_object(mem, (byte *)pfen->pattern,
  764.                "gp_enumerate_files_close(pattern)");
  765.     gs_free_object(mem, pfen, "gp_enumerate_files_close");
  766. }
  767.  
  768. /* Set a file into binary or text mode. */
  769. int
  770. gp_setmode_binary(FILE * pfile, bool binary)
  771. {
  772.     return 0;            /* Fake out dos return status */
  773. }
  774.  
  775. /***************************************************************************/
  776. /*         Functions from ixemul.library source which aren't in Libnix     */
  777. /***************************************************************************/
  778. #ifndef IXEMUL
  779.  
  780. /***************************************************************************/
  781. /*                                     modf.c                              */
  782. /***************************************************************************/
  783. #include <proto/mathieeedoubbas.h>
  784.  
  785. /*
  786.  * modf(value, iptr): return fractional part of value, and stores the
  787.  * integral part into iptr (a pointer to double).
  788.  */
  789.  
  790. double
  791. modf (double value, double *iptr)
  792. {
  793.   /* if value negative */
  794.   if (IEEEDPTst (value) < 0)
  795.     {
  796.       /* in that case, the integer part is calculated by ceil() */
  797.       *iptr = IEEEDPCeil (value);
  798.       return IEEEDPSub (*iptr, value);
  799.     }
  800.   else
  801.     {
  802.  
  803.       /* if positive, we go for the floor() */
  804.       *iptr = IEEEDPFloor (value);
  805.       return IEEEDPSub (value, *iptr);
  806.     }
  807. }
  808. /***************************************************************************/
  809. /*                                     frexp.c                             */
  810. /***************************************************************************/
  811. #if defined(LIBC_SCCS) && !defined(lint)
  812. static char sccsid[] = "@(#)frexp.c    5.2 (Berkeley) 3/9/86";
  813. #endif LIBC_SCCS and not lint
  814.  
  815. #define KERNEL
  816. /*#include "ixemul.h"*/
  817.  
  818. /*
  819.  *    the call
  820.  *        x = frexp(arg,&exp);
  821.  *    must return a double fp quantity x which is <1.0
  822.  *    and the corresponding binary exponent "exp".
  823.  *    such that
  824.  *        arg = x*2^exp
  825.  *    if the argument is 0.0, return 0.0 mantissa and 0 exponent.
  826.  */
  827.  
  828. double
  829. frexp(double x, int *i)
  830. {
  831.   int neg;
  832.   int j;
  833.  
  834.   j = 0;
  835.   neg = 0;
  836.  
  837.   if (x < 0)
  838.     {
  839.       x = -x;
  840.       neg = 1;
  841.     }
  842.  
  843.   if (x >= 1.0)
  844.     while(x >= 1.0)
  845.       {
  846.     j = j+1;
  847.     x = x/2;
  848.       }
  849.   else if(x < 0.5 && x != 0.0)
  850.     while(x < 0.5)
  851.       {
  852.     j = j-1;
  853.     x = 2*x;
  854.       }
  855.  
  856.   *i = j;
  857.   if (neg) x = -x;
  858.   return x;
  859. }
  860.  
  861. /***************************************************************************/
  862. /*                                     ldexp.c                             */
  863. /***************************************************************************/
  864. /*
  865.  * ldexp returns the quanity "value" * 2 ^ "exp"
  866.  *
  867.  * For the mc68000 using IEEE format the double precision word format is:
  868.  *
  869.  * WORD N   =>    SEEEEEEEEEEEMMMM
  870.  * WORD N+1 =>    MMMMMMMMMMMMMMMM
  871.  * WORD N+2 =>    MMMMMMMMMMMMMMMM
  872.  * WORD N+3 =>    MMMMMMMMMMMMMMMM
  873.  *
  874.  * Where:          S  =>   Sign bit
  875.  *                 E  =>   Exponent
  876.  *                 X  =>   Ignored (set to 0)
  877.  *                 M  =>   Mantissa bit
  878.  *
  879.  * NOTE:  Beware of 0.0; on some machines which use excess 128 notation for the
  880.  * exponent, if the mantissa is zero the exponent is also.
  881.  *
  882.  */
  883.  
  884. #define MANT_MASK 0x800FFFFF    /* Mantissa extraction mask     */
  885. #define ZPOS_MASK 0x3FF00000    /* Positive # mask for exp = 0  */
  886. #define ZNEG_MASK 0x3FF00000    /* Negative # mask for exp = 0  */
  887.  
  888. #define EXP_MASK 0x7FF00000    /* Mask for exponent            */
  889. #define EXP_SHIFTS 20        /* Shifts to get into LSB's     */
  890. #define EXP_BIAS 1023        /* Exponent bias                */
  891.  
  892.  
  893. union dtol
  894. {
  895.   double dval;
  896.   int ival[2];
  897. };
  898.  
  899. double
  900. ldexp (value, exp)
  901.      double value;
  902.      int exp;
  903. {
  904.   union dtol number;
  905.   int *iptr, cexp;
  906.  
  907.   if (value == 0.0)
  908.     return (0.0);
  909.   else
  910.     {
  911.       number.dval = value;
  912.       iptr = &number.ival[0];
  913.       cexp = (((*iptr) & EXP_MASK) >> EXP_SHIFTS) - EXP_BIAS;
  914.       *iptr &= ~EXP_MASK;
  915.       exp += EXP_BIAS;
  916.       *iptr |= ((exp + cexp) << EXP_SHIFTS) & EXP_MASK;
  917.       return (number.dval);
  918.     }
  919. }
  920. #endif
  921.